package component

import "sync"

type (
	// EndpointMeta 元数据
	EndpointMeta struct {
		MetaKey     string      `json:"metaKey" yaml:"metaKey"`         // 元数据键，唯一标识
		Application string      `json:"application" yaml:"application"` // 所属应用名
		HttpMethod  string      `json:"httpMethod" yaml:"httpMethod"`   // 请求方法，如：GET
		HttpPattern string      `json:"httpPattern" yaml:"httpPattern"` // 请求路径，如：/users/{id}
		Version     string      `json:"version" yaml:"version"`         // 版本号，如：1.0
		Protocol    string      `json:"protocol" yaml:"protocol"`       // 协议，如：http、echo or 自定义协议
		ServerId    string      `json:"serverId" yaml:"serverId"`       // 所属服务器ID，如：注册接口到网关服务器 or 注册接口到Admin服务器
		Service     ServiceMeta `json:"service" yaml:"service"`         // 上游/后端服务（endpoint注解，绑定的后端服务信息）
	}

	ServiceMeta struct {
		MetaKey   string            `json:"metaKey" yaml:"metaKey"`         // Service类型
		Url       string            `json:"httpPattern" yaml:"httpPattern"` // Service侧的URL
		Protocol  string            `json:"protocol" yaml:"protocol"`       // Service侧后端协议
		Interface string            `json:"interface" yaml:"interface"`     // Service侧的Interface
		Method    string            `json:"method" yaml:"method"`           // Service侧的Method
		Arguments []ServiceArgument `json:"arguments" yaml:"arguments"`     // Service侧的参数结构
	}

	ServiceArgument struct {
		Name         string            `json:"name" yaml:"name"`           // 参数名称
		StructType   string            `json:"type" yaml:"type"`           // 参数结构类型
		ClassType    string            `json:"class" yaml:"class"`         // 参数类型
		HttpName     string            `json:"httpName" yaml:"httpName"`   // 映射Http的参数Key
		HttpScope    string            `json:"httpScope" yaml:"httpScope"` // 映射Http参数值域
		Fields       []ServiceArgument `json:"fields" yaml:"fields"`
		Required     bool              `json:"required" yaml:"required"`         // 是否必须
		DefaultValue string            `json:"defaultValue" yaml:"defaultValue"` // 默认值
	}

	// EndpointMVCC 元数据多版本控制
	EndpointMVCC struct {
		multiVersion  map[string]*EndpointMeta // 多版本元数据
		*sync.RWMutex                          // 读写锁
	}
)

// NewEndpointMeta 创建元数据
func NewEndpointMeta(metaKey, application, httpMethod, httpPattern, version, protocol, serverId string, service ServiceMeta) *EndpointMeta {
	return &EndpointMeta{
		MetaKey:     metaKey,
		Application: application,
		HttpMethod:  httpMethod,
		HttpPattern: httpPattern,
		Version:     version,
		Protocol:    protocol,
		ServerId:    serverId,
		Service:     service,
	}
}

func NewServiceMeta(metaKey, url, protocol, interfaceName, method string, arguments []ServiceArgument) ServiceMeta {
	return ServiceMeta{
		MetaKey:   metaKey,
		Url:       url,
		Protocol:  protocol,
		Interface: interfaceName,
		Method:    method,
		Arguments: arguments,
	}
}

// NewEndpointMVCC 创建元数据多版本控制
func NewEndpointMVCC(metadata *EndpointMeta) *EndpointMVCC {
	return &EndpointMVCC{
		multiVersion: map[string]*EndpointMeta{
			metadata.Version: metadata,
		},
		RWMutex: &sync.RWMutex{},
	}
}

// Lookup 查找指定版本号的Endpoint元数据
func (m *EndpointMVCC) Lookup(version string) (*EndpointMeta, bool) {
	m.RLock()
	defer m.RUnlock()
	size := len(m.multiVersion)
	if 0 == size {
		return nil, false
	}
	epv, ok := m.multiVersion[version]
	if !ok {
		return nil, false
	}
	return epv, true
}

// Update 更新指定版本号的Endpoint元数据
func (m *EndpointMVCC) Update(version string, endpoint *EndpointMeta) {
	m.Lock()
	m.multiVersion[version] = endpoint
	m.Unlock()
}

// Delete 删除指定版本号的Endpoint元数据
func (m *EndpointMVCC) Delete(version string) {
	m.Lock()
	delete(m.multiVersion, version)
	m.Unlock()
}

// Endpoints 获取当前多版本控制器的全部Endpoint元数据列表
func (m *EndpointMVCC) Endpoints() []*EndpointMeta {
	m.RLock()
	copies := make([]*EndpointMeta, 0, len(m.multiVersion))
	for _, ep := range m.multiVersion {
		copies = append(copies, ep)
	}
	m.RUnlock()
	return copies
}
